package com.gali.juc;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.StampedLock;

/**
 * @Auther: gali
 * @Date: 2022-08-29 16:46
 * @Description:
 */
public class StampedLockDemo {
    static int num=37;
    static StampedLock stampedLock=new StampedLock();

    public void write(){
        long stamp = stampedLock.writeLock();
        System.out.println(Thread.currentThread().getName()+"\t"+"写线程准备修改");
        try {
            num=num+13;
        } finally {
            stampedLock.unlockWrite(stamp);
        }
        System.out.println(Thread.currentThread().getName()+"\t"+"写线程结束修改");
    }

    public void read(){
        long stamp = stampedLock.readLock();
        System.out.println(Thread.currentThread().getName()+"\t"+"come in");
        for (int i = 0; i < 4; i++) {
            try {
                TimeUnit.SECONDS.sleep(4);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+"\t"+"正在读取中");
        }

        try {
            int result = num;
            System.out.println(Thread.currentThread().getName()+"\t"+"获得成员变量值："+result);
            System.out.println(Thread.currentThread().getName()+"\t"+"写线程没有成功");

        } finally {
            stampedLock.unlockRead(stamp);
        }
    }


    public void tryOptimisticRead(){
        long stamp = stampedLock.tryOptimisticRead();
        int result=num;
        System.out.println("4秒前 true表示无修改，false表示有修改"+"\t"+stampedLock.validate(stamp));
        for (int i = 0; i < 4; i++) {
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+"\t"+"正在读取"+i+"秒后"+stampedLock.validate(stamp));
            if (!stampedLock.validate(stamp)){
                System.out.println("有人修改");
                stamp = stampedLock.readLock();
                try {
                    System.out.println("从乐观锁，升级为悲观");
                    result=num;
                    System.out.println("重新悲观读后res"+result);
                } finally {
                    stampedLock.unlockRead(stamp);
                }
            }
            System.out.println(Thread.currentThread().getName()+"\t"+"finally value:"+result);
        }
    }
    public static void main(String[] args) {
//        old();
        newStamp();
    }

    private static void newStamp() {
        StampedLockDemo stampedLockDemo = new StampedLockDemo();
        new Thread(()->{
            stampedLockDemo.tryOptimisticRead();
        },"a").start();
        try {
            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        new Thread(()->{
            System.out.println(Thread.currentThread().getName()+"\t"+"come in ");
            stampedLockDemo.write();
        },"b").start();
    }

    private static void old() {
        StampedLockDemo stampedLockDemo = new StampedLockDemo();
        new Thread(()->{
            stampedLockDemo.read();
        },"a").start();
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        new Thread(()->{
            stampedLockDemo.write();
        },"b").start();
    }
}
